#include <stdio.h>
#include <stdbool.h>
#include "MyString.h"

size_t MyStrlen(const char *s)
{
    size_t count = 0;
    while (*s++ != '\0')
    {
        count++;
    }
    return count;
}

void Mystrcpy(char *dest, const char *src)
{
    while (*src != '\0')
    {
        *dest++ = *src++;
    }
    *dest = '\0';
}

void Mystrncpy(char *dest, const char *src, size_t n)
{
    while (*src != '\0' && n-- != 0)
    {
        *dest++ = *src++;
    }
    *dest = '\0';
}

int MyStrcmy(const char *s1, const char *s2)
{
    while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')
    {
        s1++;
        s2++;
        return *s1 - *s2;
    }
}

#define Min(a, b) (a) < (b) ? a : b
int MyStrncmy(const char *s1, const char *s2, size_t n)
{
    size_t minLen = Min(Min(MyStrlen(s1), MyStrlen(s2)), n); // 得到最小长度
    if (minLen == n)
    {
        while (*s1 == *s2 && minLen != 1) // 留最后一个字符给做减法
        {
            s1++;
            s2++;
            minLen--;
        }
        return *s1 - *s2;
    }
    else // n不是最小值时，比较的就是原字符串的大小
    {
        return MyStrcmy(s1, s2);
    }
}

void MyStrcat(char *dest, const char *src)
{
    Mystrcpy(dest + MyStrlen(dest), src);
}

void MyStrncat(char *dest, const char *src, size_t n)
{
    Mystrncpy(dest + MyStrlen(dest), src, n);
}

// 滑动窗口寻找
char *MyStrstr(char *dest, const char *src)
{
    size_t dlen = MyStrlen(dest);
    size_t slen = MyStrlen(src);
    for (int i = 0; i < dlen - slen; i++)
    {
        if (MyStrncmy(dest + i, src, slen) == 0)
        {
            return dest + i;
        }
    }
    return NULL;
}

bool IsHaveChar(const char *s, char c)
{
    while (*s != '\0')
    {
        if (*s == c)
        {
            return true;
        }
        s++;
    }
    return false;
}

char *MyStrtok(char *src, const char *delim)
{
    // 上一次切割完的下一个字符串
    static char *nextStr = NULL;
    if (src == NULL) // 想要继续切割上一次的字符串
    {
        src = nextStr;
    }
    if (src == NULL) // 没有字符串可以被操作
    {
        return NULL;
    }
    // 跳过所有的分隔符
    while (*src != '\0')
    {
        // 判断是否是分隔符
        if (IsHaveChar(delim, *src) == true)
        {
            src++; // 是分隔符就不要，继续往前找
        }
        else
        {
            break; // 找到了第一个不是分隔符的位置
        }
    }
    if (*src == '\0')
    {
        return NULL;
    }
    // src:有效字符串的首地址
    // 找下一个分隔符
    char *end = src;
    while (*end != '\0')
    {
        // 是下一个分隔符
        if (IsHaveChar(delim, *end) == true)
        {
            break;
        }`
        else
        {
            end++;
        }
    }
    if (*end == '\0') // 没有下一个字符串可以切割了
    {
        nextStr = NULL;
    }
    else
    {
        *end = '\0';
        nextStr = end + 1;
    }
    return src;
}

int main()
{
    // printf("%ld\n", MyStrlen("helloworld"));
    // const char *s = "hello";
    // char str[6] = {0};
    // Mystrncpy(str, s, 3);
    // printf("%s\n", str);

    // const char *s1 = "hello";
    // const char *s2 = "helloaorld";
    // printf("%d\n", MyStrncmy(s1, s2, 100));

    // const char *s = "world";
    // char str[10] = "hello";
    // MyStrncat(str, s, 3);
    // printf("%s\n", str);

    // char str[20] = "helloworld";
    // const char *s = "llo";
    // char *a = MyStrstr(str, s);
    // printf("%s\n", a);

    char str[] = "zhangsan,lisi,wangwu";
    char *s = MyStrtok(str, ",.");
    while (s != NULL)
    {
        printf("%s\n", s);
        s = MyStrtok(NULL, ",.");
    }
    return 0;
}
